#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
#include <pthread.h>
#include <stdbool.h>

/*--------------------- 配置参数 ---------------------*/
#define SERIAL_COUNT         16
#define BAUDRATE            B115200
#define TEST_STR_FORMAT     "%s serial-%d test"
#define RESP_TIMEOUT_MS     1000   // 单次接收超时时间
#define MAX_RETRIES         3     // 最大重试次数

// 协议范围结构体
typedef struct {
    int first;
    int last;
} SerialRange;

// 各协议范围宏
#define RS232_RANGE  {0, 5}
#define RS422_RANGE  {6, 9}
#define RS485_RANGE  {10, 15}

const char *serial_ports[SERIAL_COUNT] = {
    "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3",
    "/dev/ttyS4", "/dev/ttyS5", "/dev/ttyS6", "/dev/ttyS7",
    "/dev/ttyS8", "/dev/ttyS9", "/dev/ttyS10", "/dev/ttyS11",
    "/dev/ttyS12", "/dev/ttyS13", "/dev/ttyS14", "/dev/ttyS15"
};

/*--------------------- 数据结构 ---------------------*/
typedef struct {
    int fd;
    int port_num;
    char proto_name[8];
    bool test_result;
} SerialTestContext;

/*--------------------- 串口操作函数 ---------------------*/
int configure_serial(int fd) 
{
    struct termios tty;
    if ( tcgetattr(fd, &tty) ) 
    {
        return -1;
    }
    

    // 基础配置
    cfsetispeed(&tty, BAUDRATE);
    cfsetospeed(&tty, BAUDRATE);
    tty.c_cflag &= ~PARENB;        // 无校验
    tty.c_cflag &= ~CSTOPB;        // 1位停止位
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;            // 8数据位
    tty.c_cflag &= ~CRTSCTS;       // 无硬件流控
    tty.c_cflag |= CREAD | CLOCAL; // 启用接收

    // 原始模式
    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // 无软件流控
    tty.c_oflag &= ~OPOST;

    // 非阻塞读取
    tty.c_cc[VMIN] = 0;
    tty.c_cc[VTIME] = 0;

    return tcsetattr(fd, TCSANOW, &tty);
}

int open_serial(const char *dev) {
    int fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd == -1) return -1;
    if (configure_serial(fd) == -1) {
        close(fd);
        return -1;
    }
    tcflush(fd, TCIOFLUSH);
    return fd;
}

/*--------------------- 测试线程函数 ---------------------*/
void* test_thread(void *arg) {
    SerialTestContext *ctx = (SerialTestContext*)arg;
    
    // 构造测试数据
    char send_buf[64];
    snprintf(send_buf, sizeof(send_buf), "%s serial-%d test", 
             ctx->proto_name, ctx->port_num);
    
    // 带重试的发送接收
    for (int retry = 0; retry < MAX_RETRIES; retry++) {
        // 发送数据
        if (write(ctx->fd, send_buf, strlen(send_buf)) < 0) {
            usleep(100000);
            continue;
        }
        usleep(50000);
        printf( "发送数据:%s\n", send_buf );
        // 等待响应
        struct pollfd pfd = { .fd = ctx->fd, .events = POLLIN };
        char recv_buf[64] = {0};
        int total_recv = 0;
        bool timeout = false;
        
        while (!timeout && total_recv < strlen(send_buf)) {
            int ret = poll(&pfd, 1, RESP_TIMEOUT_MS);
            if (ret > 0) {
                int n = read(ctx->fd, recv_buf + total_recv, 
                           sizeof(recv_buf) - total_recv - 1);
                if (n > 0) total_recv += n;
            } else {
                timeout = true;
            }
        }
        
        // 验证响应
        if (!timeout && strncmp(send_buf, recv_buf, strlen(send_buf)) == 0) {
            ctx->test_result = true;
            printf( "收到响应::%s\n", recv_buf );
            break;
        }
        printf( "接收超时\n" );
    }
    printf("%s %s 通道%d %s 测试 %s\n\n",
                ctx->test_result ? "✅" : "❌",
                ctx->proto_name,
                ctx->port_num,
                serial_ports[ctx->port_num],
                ctx->test_result ? "通过" : "失败");

    
    close(ctx->fd);
    return NULL;
}

/*--------------------- 测试控制函数 ---------------------*/
void run_concurrent_test(SerialRange range, const char *proto_name) {
    pthread_t threads[SERIAL_COUNT];
    SerialTestContext contexts[SERIAL_COUNT];
    int active_count = 0;
    
    // 创建测试线程
    for (int i = range.first; i <= range.last; i++) 
    {
        contexts[active_count].port_num = i;
        strncpy(contexts[active_count].proto_name, proto_name, 8);
        contexts[active_count].test_result = false;
        
        int fd = open_serial(serial_ports[i]);
        if (fd == -1) {
            printf("❌ %s %s 打开失败\n", proto_name, serial_ports[i]);
            continue;
        }
        
        contexts[active_count].fd = fd;
        pthread_create(&threads[active_count], NULL, test_thread, &contexts[active_count]);
        
        sleep(2);  //1s
        active_count++;

    }
    
    // 等待所有线程完成
    for (int i = 0; i < active_count; i++) {
        pthread_join(threads[i], NULL);
        
    }
}

int test_all_serial_ports() {
    // // 定义测试配置：类型、范围、测试次数
    // const struct {
    //     SerialRange range;
    //     const char* name;
    //     int times;
    // } tests[] = {
    //     {RS232_RANGE, "RS232", 3},
    //     {RS422_RANGE, "RS422", 3},
    //     {RS485_RANGE, "RS485", 3}
    // };
    // const char* suffixes[] = {"First", "Second", "Third"};
    
    // // 遍历所有测试配置
    // for (int i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
    //     // 每组测试前添加空行（除第一组外）
    //     if (i > 0) printf("\n");
        
    //     // 执行当前配置的多次测试
    //     for (int j = 0; j < tests[i].times; j++) {
    //         printf("===== %s测试 %s=====\n", tests[i].name, suffixes[j]);
    //         run_concurrent_test(tests[i].range, tests[i].name);
    //         printf("\n");
    //     }
    // }
    printf("===== RS232测试 =====\n");
    run_concurrent_test((SerialRange)RS232_RANGE, "RS232");

    printf("\n===== RS422测试=====\n");
    run_concurrent_test((SerialRange)RS422_RANGE, "RS422");

    printf("\n===== RS485测试=====\n");
    run_concurrent_test((SerialRange)RS485_RANGE, "RS485");

    return 0;
}